package handlers

import (
	"net/http"
	"strconv"
	"time"

	"things_iot_backend/auth"
	"things_iot_backend/cache"
	"things_iot_backend/database"
	"things_iot_backend/models"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"gorm.io/gorm"
)

type DeviceHandler struct {
	db *gorm.DB
}

func NewDeviceHandler(db *gorm.DB) *DeviceHandler {
	return &DeviceHandler{db: db}
}

// CreateDevice 创建设备
func (h *DeviceHandler) CreateDevice(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	var req models.CreateDeviceRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误",
			"data":    nil,
		})
		return
	}

	// 生成设备UUID
	deviceUUID := uuid.New().String()

	device := models.Device{
		UserID:      userClaims.UserID,
		DeviceID:    deviceUUID,
		Name:        req.Name,
		Description: req.Description,
		DeviceType:  req.DeviceType,
		Status:      "offline",
		CreatedAt:   time.Now(),
		UpdatedAt:   time.Now(),
	}

	if err := h.db.Create(&device).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "创建设备失败",
			"data":    nil,
		})
		return
	}

	// 清除用户设备缓存
	cache.DeleteUserDevicesCache(userClaims.UserID)

	c.JSON(http.StatusCreated, gin.H{
		"code":    201,
		"message": "设备创建成功",
		"data": models.Device{
			ID:         device.ID,
			DeviceID:   device.DeviceID,
			Name:       device.Name,
			DeviceType: device.DeviceType,
			Status:     device.Status,
			CreatedAt:  device.CreatedAt,
		},
	})
}

// GetDevices 获取设备列表
func (h *DeviceHandler) GetDevices(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	// 分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	offset := (page - 1) * pageSize

	var devices []models.Device
	var total int64

	// 构建查询
	query := h.db.Model(&models.Device{})
	if !auth.IsSuperAdmin(userClaims) {
		query = query.Where("user_id = ?", userClaims.UserID)
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取设备列表失败",
			"data":    nil,
		})
		return
	}

	// 获取分页数据
	if err := query.Offset(offset).Limit(pageSize).Find(&devices).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取设备列表失败",
			"data":    nil,
		})
		return
	}

	totalPages := (int(total) + pageSize - 1) / pageSize

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data": models.DeviceListResponse{
			Devices: devices,
			Pagination: models.PaginationResponse{
				Page:       page,
				PageSize:   pageSize,
				Total:      int(total),
				TotalPages: totalPages,
			},
		},
	})
}

// GetDevice 获取设备详情
func (h *DeviceHandler) GetDevice(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权访问该设备",
			"data":    nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data":    device,
	})
}

// UpdateDevice 更新设备
func (h *DeviceHandler) UpdateDevice(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权更新该设备",
			"data":    nil,
		})
		return
	}

	var req models.UpdateDeviceRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误",
			"data":    nil,
		})
		return
	}

	// 更新设备信息
	updates := map[string]interface{}{
		"updated_at": time.Now(),
	}

	if req.Name != "" {
		updates["name"] = req.Name
	}
	if req.Description != "" {
		updates["description"] = req.Description
	}

	if err := h.db.Model(&device).Updates(updates).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "更新设备失败",
			"data":    nil,
		})
		return
	}

	// 清除缓存
	cache.DeleteUserDevicesCache(device.UserID)

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "设备更新成功",
		"data":    nil,
	})
}

// DeleteDevice 删除设备
func (h *DeviceHandler) DeleteDevice(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权删除该设备",
			"data":    nil,
		})
		return
	}

	// 删除设备
	if err := h.db.Delete(&device).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "删除设备失败",
			"data":    nil,
		})
		return
	}

	// 清除缓存
	cache.DeleteUserDevicesCache(device.UserID)
	cache.DeleteDeviceConnection(device.ID)
	cache.ClearCommandQueue(device.ID)

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "设备删除成功",
		"data":    nil,
	})
}

// GetDeviceTelemetryLatest 获取设备最新遥测数据
func (h *DeviceHandler) GetDeviceTelemetryLatest(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权访问该设备数据",
			"data":    nil,
		})
		return
	}

	// 尝试从缓存获取最新数据
	latestData, err := cache.GetDeviceLatestData(device.ID)
	if err == nil && latestData != nil {
		c.JSON(http.StatusOK, gin.H{
			"code":    200,
			"message": "success",
			"data":    latestData,
		})
		return
	}

	// 从数据库获取最新数据
	latestData, err = database.GetLatestTelemetryData(device.ID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取设备数据失败",
			"data":    nil,
		})
		return
	}

	// 缓存数据
	cache.CacheDeviceLatestData(device.ID, latestData)

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data":    latestData,
	})
}

// GetDeviceTelemetryHistory 获取设备历史遥测数据
func (h *DeviceHandler) GetDeviceTelemetryHistory(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权访问该设备数据",
			"data":    nil,
		})
		return
	}

	// 解析查询参数
	metric := c.Query("metric")
	startTimeStr := c.Query("start_time")
	endTimeStr := c.Query("end_time")
	interval := c.Query("interval")

	// 解析时间范围
	startTime := time.Now().Add(-24 * time.Hour) // 默认最近24小时
	endTime := time.Now()

	if startTimeStr != "" {
		if t, err := time.Parse(time.RFC3339, startTimeStr); err == nil {
			startTime = t
		}
	}

	if endTimeStr != "" {
		if t, err := time.Parse(time.RFC3339, endTimeStr); err == nil {
			endTime = t
		}
	}

	// 获取历史数据
	telemetry, err := database.GetTelemetryHistory(device.ID, metric, startTime, endTime, interval)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取历史数据失败",
			"data":    nil,
		})
		return
	}

	// 格式化响应数据
	response := make(map[string][]map[string]interface{})
	for _, data := range telemetry {
		// 遍历遥测数据中的所有指标
		for metricName, value := range data.TelemetryData {
			// 跳过子设备数据
			if metricName == "subdevices" {
				continue
			}
			point := map[string]interface{}{
				"time":  data.Time,
				"value": value,
			}
			response[metricName] = append(response[metricName], point)
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data":    response,
	})
}
